package com.kaibes.web.prefix;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import javax.servlet.ServletContext;

import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
import org.springframework.web.util.UrlPathHelper;

@Configuration
public class ResourceRegistrys {

    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private WebViewConfig config;
    
    private SimpleUrlHandlerMapping resourceHandlerMapping;
    
    public void unregistry(String pattern, String... resourceLocations) {
        if (resourceHandlerMapping == null) {
            resourceHandlerMapping = (SimpleUrlHandlerMapping) applicationContext.getBean("resourceHandlerMapping");
        }
        if (resourceHandlerMapping.getHandlerMap().containsKey(pattern)) {
            if (resourceLocations.length == 0) {
                resourceHandlerMapping.getHandlerMap().remove(pattern);
            } else {
                //hanlder已经注册进去了，这时候要找到handler
                ResourceHttpRequestHandler handler = (ResourceHttpRequestHandler) resourceHandlerMapping.getHandlerMap().get(pattern);
                //找到handler里的所有资源
                List<Resource> resourceList = handler.getLocations();
                for (String resourceLocation : resourceLocations) {
                    //遍历判断资源是否已存在,flag=true表示需要插入资源
                    Resource temp = null;
                    for (Resource resource : resourceList) {
                        if (resource.exists()) {
                            try {
                                String path = resource.getURI().toString();
                                if (path.equals(resourceLocation)) {
                                    temp = resource;
                                    break;
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    if (temp != null) {
                        handler.getLocations().remove(temp);
                    }
                }
            }
        }
        
    }
    
    @SuppressWarnings("deprecation")
    public void registry(String pattern, String... resourceLocations) {
        if (resourceHandlerMapping == null) {
            resourceHandlerMapping = (SimpleUrlHandlerMapping) applicationContext.getBean("resourceHandlerMapping");
        }
        
//        String key = "/files/**";
        if (!resourceHandlerMapping.getHandlerMap().containsKey(pattern)) {
            ResourceHandlerRegistration registration = new ResourceHandlerRegistration(pattern);
//            registration.addResourceLocations("file:files1/");
            registration.addResourceLocations(resourceLocations);
            try {
                //创建一个handler
                Method method = ResourceHandlerRegistration.class.getDeclaredMethod("getRequestHandler");
                method.setAccessible(true);
                ResourceHttpRequestHandler handler = (ResourceHttpRequestHandler) method.invoke(registration);
                //初始化handler 1
//                Field field = ResourceHandlerRegistry.class.getDeclaredField("pathHelper");
//                field.setAccessible(true);
//                UrlPathHelper urlPathHelper = (UrlPathHelper) field.get(appConfig.registry);
                UrlPathHelper urlPathHelper = resourceHandlerMapping.getUrlPathHelper();
                if (urlPathHelper != null) {
                    handler.setUrlPathHelper(urlPathHelper);
                }
                //初始化handler 2
                Field field = ResourceHandlerRegistry.class.getDeclaredField("contentNegotiationManager");
                field.setAccessible(true);
                ContentNegotiationManager contentNegotiationManager = (ContentNegotiationManager) field.get(config.getRegistry());
                if (contentNegotiationManager != null) {
                    handler.setContentNegotiationManager(contentNegotiationManager);
                }
                //初始化handler 3
                field = ResourceHandlerRegistry.class.getDeclaredField("servletContext");
                field.setAccessible(true);
                ServletContext servletContext = (ServletContext) field.get(config.getRegistry());
                handler.setServletContext(servletContext);
                handler.setApplicationContext(this.applicationContext);
                try {
                    handler.afterPropertiesSet();
                }
                catch (Throwable ex) {
                    throw new BeanInitializationException("Failed to init ResourceHttpRequestHandler", ex);
                }
                //注册handler
                method = AbstractUrlHandlerMapping.class.getDeclaredMethod("registerHandler", String.class, Object.class);
                method.setAccessible(true);
                method.invoke(resourceHandlerMapping, pattern, handler);
            } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchFieldException e) {
                e.printStackTrace();
            }
        } else {
            //hanlder已经注册进去了，这时候要找到handler
            ResourceHttpRequestHandler handler = (ResourceHttpRequestHandler) resourceHandlerMapping.getHandlerMap().get(pattern);
            //找到handler里的所有资源
            List<Resource> resourceList = handler.getLocations();
            for (String resourceLocation : resourceLocations) {
                //遍历判断资源是否已存在,flag=true表示需要插入资源
                boolean flag = true;
                for (Resource resource : resourceList) {
                    if (resource.exists()) {
                        try {
                            String path = resource.getURI().toString();
                            if (path.equals(resourceLocation)) {
                                flag = false;
                                break;
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
                //插入资源
                if (flag) {
                    Resource resource = applicationContext.getResource(resourceLocation);
                    handler.getLocations().add(resource);
                }
            }
        }
    }
}
